// addon.cc
#include <node.h>
#include <node_api.h>
#include "loadcontainer.h"

using namespace v8;
CLoadContainer* pConatainer = NULL;

namespace app
{

using v8::Context;
using v8::Exception;
using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::NewStringType;
using v8::Object;
using v8::String;
using v8::Value;

#define WRONG_STRING String::NewFromUtf8(isolate, "Wrong arguments").ToLocalChecked()
#define PARAM_THROW  isolate->ThrowException(Exception::TypeError(WRONG_STRING))

//////////////////////////////////////////////////////////////////////////
void CreateInstanceFunc(const FunctionCallbackInfo<Value>& args)
{
    Isolate* isolate = args.GetIsolate();
    c_error(isolate != NULL);

    pConatainer = ALLOC_NEW CLoadContainer();
}

void DestoryInstanceFunc(const FunctionCallbackInfo<Value>& args)
{
    c_error(pConatainer != NULL);
    delete pConatainer;
}

void StartInstanceFunc(const FunctionCallbackInfo<Value>& args)
{
    c_error(pConatainer != NULL) logi("pConatainer==>%s", "ok");

    Isolate* isolate = args.GetIsolate();
    c_error(isolate != NULL);

    if (args.Length() < 2) {
        PARAM_THROW;
        logi("args==>%s", "error");
        return;
    }

    if (!args[0]->IsString() || !args[1]->IsString()) {
        PARAM_THROW;
        logi("args_type==>%s", "error");
        return;
    }

    //////////////////////////////////////////////////////////////////////////
    Local<Context> context = Context::New(isolate);
    v8::String::Utf8Value str_args_1(isolate, args[0]->ToString(context).ToLocalChecked());
    v8::String::Utf8Value str_args_2(isolate, args[1]->ToString(context).ToLocalChecked());
    //////////////////////////////////////////////////////////////////////////

    logi("std_com==>%s", *str_args_1);
    logi("license_code==>%s", *str_args_2);
    pConatainer->Init(NULL, *str_args_1, *str_args_2);
    pConatainer->Start(NULL, 0);
}

void StopInstanceFunc(const FunctionCallbackInfo<Value>& args)
{
    c_error(pConatainer != NULL);
    pConatainer->Stop(NULL, 0, 0);
    pConatainer->UnInit(NULL);
}
//////////////////////////////////////////////////////////////////////////
void PostMessageFunc(const FunctionCallbackInfo<Value>& args)
{
}

void SendMessageFunc(const FunctionCallbackInfo<Value>& args)
{
}

void RecvMessageFunc(const FunctionCallbackInfo<Value>& args)
{
}

void NotifyMessageFunc(const FunctionCallbackInfo<Value>& args)
{
}
//////////////////////////////////////////////////////////////////////////
void CreateObject(const FunctionCallbackInfo<Value>& args)
{
    Isolate* isolate = args.GetIsolate();
    Local<Context> context = isolate->GetCurrentContext();

    Local<Object> obj = Object::New(isolate);
    obj->Set(context, String::NewFromUtf8(isolate, "msg", NewStringType::kNormal).ToLocalChecked(), args[0]->ToString(context).ToLocalChecked())
        .FromJust();
    args.GetReturnValue().Set(obj);
}
//////////////////////////////////////////////////////////////////////////
void Initialize(Local<Object> exports, Local<Value> module, void* priv)
{
    // NODE_SET_METHOD(module, "exports", CreateObject);
    //////////////////////////////////////////////////////////////////////////
    NODE_SET_METHOD(exports, "create", CreateInstanceFunc);
    NODE_SET_METHOD(exports, "destory", DestoryInstanceFunc);
    NODE_SET_METHOD(exports, "start", StartInstanceFunc);
    NODE_SET_METHOD(exports, "stop", StopInstanceFunc);
    //////////////////////////////////////////////////////////////////////////
    NODE_SET_METHOD(exports, "postmessage", PostMessageFunc);
    NODE_SET_METHOD(exports, "sendmessage", SendMessageFunc);
    NODE_SET_METHOD(exports, "recvmessage", RecvMessageFunc);
    NODE_SET_METHOD(exports, "notifymessage", NotifyMessageFunc);
}

NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize);
} // namespace app
